import { ModelFrom, ModelType } from "@/constants/Enums";
import { MTreeNode } from "@/common/Tree/MTreeNode";
import { modelService } from "@/modules/model/service";
import { reactive, nextTick } from "vue";
import { DiagramCustomizationManagementModel } from "../../DiagramCustomizationManagementModel";
import { CheckValidPropertyValueDto } from "@/modules/model/service/dto";
import { SelectableNodeData } from "@/modules/model/project/IGraphNode";
import { SortNodeUtil } from "@/modules/model/project/SortNodeUtil";
import { PropertyRow } from "@/modules/model/comps/station/sider/attribute/types";
import { MetaclassType } from "@/constants/MetaclassType";
import { ContainElementModel } from "../containElementComps/ContainElementModel";
import { ComponentConfigurationModel } from "../componentsConfigurationComps/ComponentConfigurationModel";
import { getUid } from "@/util/common";
import { ShapeKey } from "@/mdesign-lib/mdesign-graph.umd.js";

type QueryParams = {
  projectId: string;
  modelId: string;
  row: any;
};
export type CommonNode = {
  selectable: boolean;
  selected: boolean;
  disabled: boolean;
  hasChild: boolean;
  icon: string;
  id: string;
  name: string;
  cnName: string;
  enName: string;
  key: string;
  shapeKey: ShapeKey;
};
type CommonTreeData = {
  selectable: boolean;
  selected: boolean;
  expand?: boolean;
  icon: string;
  id: string;
  hasChild?: boolean;
  cnName: string;
  enName: string;
  children: CommonNode[];
};

export const commonTreeDataDefault: CommonTreeData[] = [
  {
    selectable: false,
    selected: false,
    expand: true,
    icon: "statics/images/sysml/Model.svg",
    id: getUid(),
    hasChild: true,
    cnName: "通用",
    enName: "通用",
    children: [
      {
        selectable: true,
        selected: false,
        disabled: false,
        icon: "/statics/images/sysml/Note.svg",
        id: getUid(),
        hasChild: false,
        name: "注释",
        cnName: "注释",
        enName: "Note",
        key: "Note",
        shapeKey: ShapeKey.Note
      },
      {
        selectable: true,
        selected: false,
        disabled: false,
        icon: "/statics/images/sysml/Anchor.svg",
        id: getUid(),
        hasChild: false,
        name: "注释线",
        cnName: "注释线",
        enName: "Anchor",
        key: "Anchor",
        shapeKey: ShapeKey.Anchor
      },
      {
        selectable: true,
        selected: false,
        disabled: false,
        icon: "/statics/images/sysml/Containment.svg",
        id: getUid(),
        hasChild: false,
        name: "包含",
        cnName: "包含",
        enName: "Containment",
        key: "Containment",
        shapeKey: ShapeKey.Containment
      },
      {
        selectable: true,
        selected: false,
        disabled: false,
        icon: "/statics/images/sysml/Metaclass.svg",
        id: getUid(),
        hasChild: false,
        name: "元类",
        cnName: "元类",
        enName: "Metaclass",
        key: "ChooseMetaclass",
        shapeKey: ShapeKey.ChooseMetaclass
      },
      {
        selectable: true,
        selected: false,
        disabled: false,
        icon: "/statics/images/sysml/ImageShape.svg",
        id: getUid(),
        hasChild: false,
        name: "图片",
        cnName: "图片",
        enName: "Image Shape",
        key: "ImageShape",
        shapeKey: ShapeKey.ImageShape
      },
      {
        selectable: true,
        selected: false,
        disabled: false,
        icon: "/statics/images/sysml/TextBox.svg",
        id: getUid(),
        hasChild: false,
        name: "文本框",
        cnName: "文本框",
        enName: "Text Box",
        key: "TextBox",
        shapeKey: ShapeKey.TextBox
      },
      {
        selectable: true,
        selected: false,
        disabled: false,
        icon: "/statics/images/sysml/HorizontalSeparator.svg",
        id: getUid(),
        hasChild: false,
        name: "水平分隔线",
        cnName: "水平分隔线",
        enName: "Horizontal Separator",
        key: "HorizontalSeparator",
        shapeKey: ShapeKey.HorizontalSeparator
      },
      {
        selectable: true,
        selected: false,
        disabled: false,
        icon: "/statics/images/sysml/VerticalSeparator.svg",
        id: getUid(),
        hasChild: false,
        name: "垂直分隔线",
        cnName: "垂直分隔线",
        enName: "Vertical Separator",
        key: "VerticalSeparator",
        shapeKey: ShapeKey.VerticalSeparator
      },
      {
        selectable: true,
        selected: false,
        disabled: false,
        icon: "/statics/images/sysml/RectangularShape.svg",
        id: getUid(),
        hasChild: false,
        name: "矩形分隔线",
        cnName: "矩形分隔线",
        enName: "Rectangular Shape",
        key: "RectangularShape",
        shapeKey: ShapeKey.RectangularShape
      },
      {
        selectable: true,
        selected: false,
        disabled: false,
        icon: "/statics/images/sysml/ContentShape.svg",
        id: getUid(),
        hasChild: false,
        name: "创建目录",
        cnName: "创建目录",
        enName: "Content Shape",
        key: "ContentShape",
        shapeKey: ShapeKey.ContentShape
      },
      {
        selectable: true,
        selected: false,
        disabled: false,
        icon: "/statics/images/sysml/CreateDiagram.svg",
        id: getUid(),
        hasChild: false,
        name: "创建视图",
        cnName: "创建视图",
        enName: "Create Diagram",
        key: "CreateDiagram",
        shapeKey: ShapeKey.CreateDiagram
      },
      {
        selectable: true,
        selected: false,
        disabled: false,
        icon: "/statics/images/sysml/PresentationFlow.svg",
        id: getUid(),
        hasChild: false,
        name: "演示流程",
        cnName: "演示流程",
        enName: "Presenttation Flow",
        key: "PresentationFlow",
        shapeKey: ShapeKey.PresentationFlow
      }
    ]
  }
];
export class TreeSelectModel {
  containElementModel: ContainElementModel;
  componentConfigurationModel: ComponentConfigurationModel;
  lazy = false;
  loading = false;
  currentProjectId = "";
  nodeMap: Map<string, MTreeNode<SelectableNodeData>> = new Map();
  nodeCommonMap: Map<string, CommonNode> = new Map();
  selectedNode: MTreeNode<SelectableNodeData> | null = null;
  selectedId = "";
  inputSearch = "";
  curTab = "tree";
  treeData: MTreeNode<SelectableNodeData>[] = [];
  checkable = false;
  showNodeLabel = true;
  checkPropertyValueDto?: CheckValidPropertyValueDto;
  queryParams: QueryParams;
  rowParams: PropertyRow;

  commonTreeData: CommonTreeData[] = commonTreeDataDefault;
  selectedCommonNode: CommonNode | null = null;

  isModelDisabled: boolean;

  get visibleDataLength() {
    const list = this.treeData.filter(item => item.show);
    return list.length;
  }

  get disableSelected() {
    if (this.curTab === "tree") {
      return !this.selectedNode || this.selectedNode.disabled || !this.selectedNode.data.selectable || this.isModelDisabled;
    } else if (this.curTab === "common") {
      return !this.selectedCommonNode || this.selectedCommonNode.disabled || !this.selectedCommonNode.selectable || this.isModelDisabled;
    }
  }

  constructor(
    public diagramCustomizationManagementModel: DiagramCustomizationManagementModel,
    public entryComp: "compsconfiguration" | "containElement"
  ) {
    /*   this.stereotypeModelId = query.stereotypeModelId;
    this.constraintModelId = query.constraintModelId; */
    this.entryComp = entryComp;
    this.containElementModel = diagramCustomizationManagementModel.containElementModel;
    this.componentConfigurationModel = diagramCustomizationManagementModel.componentConfigurationModel;
    this.lazy = true;
    this.queryParams = diagramCustomizationManagementModel.queryParams;
    this.rowParams = this.queryParams?.row && JSON.parse(this.queryParams?.row);
    this.currentProjectId = this.queryParams?.projectId;
    this.isModelDisabled = diagramCustomizationManagementModel.isModelDisabled;
    this.checkPropertyValueDto = {
      checkMethod: this.rowParams?.checkMethod || "",
      ids: [],
      instanceId: this.rowParams?.modelId,
      key: this.rowParams?.key,
      moreBtnCondition: this.rowParams?.moreBtnCondition || "",
      projectId: this.queryParams?.projectId
    };
  }

  async initData() {
    this.loading = true;
    // 将通用的元素塞到nodeMap里
    this.commonTreeData[0].children.forEach(item => {
      this.nodeCommonMap.set(item.id as string, item);
    });
    this.formateCommonComps();
    await this.loadLazyData();
    this.loading = false;
  }
  async loadLazyData() {
    const rootNode = await this.loadRootNode();
    this.nodeMap.set(rootNode.id as string, rootNode);
    await this.loadNodes(rootNode);
    rootNode.expand = true;
  }

  async loadRootNode() {
    let rootData;
    rootData = await modelService.getSelectableRootNode(this.currentProjectId, this.checkPropertyValueDto!);
    const node = this.createNode(rootData as SelectableNodeData);
    this.treeData = [node];
    return node;
  }

  createNode(nodeData: SelectableNodeData): MTreeNode<SelectableNodeData> {
    const node = reactive({
      data: nodeData,
      id: nodeData.id,
      icon: nodeData.icon,
      expand: false,
      selected: false,
      parentId: nodeData.ownerId,
      children: [],
      isLeaf: !nodeData.hasChild,
      loading: false,
      loaded: false,
      disabled: false,
      show: true
    });
    return this.formatNode(node);
  }

  formatNode(nodeData: MTreeNode<SelectableNodeData>) {
    nodeData.show = true;
    if (this.entryComp === "compsconfiguration") {
      this.componentConfigurationModel.siderbarConfig.forEach(item => {
        item.children.forEach(() => {
          /* if (nodeData?.data.metaclass && comp?.id === nodeData?.data?.id as string) {
            nodeData.disabled = true;
          } */
        });
      });
    }

    if (this.entryComp === "containElement") {
      this.containElementModel.elementRange.forEach(item => {
        if (item?.id === (nodeData?.data?.id as string)) {
          nodeData.disabled = true;
        }
      });
    }

    if (nodeData.id === this.selectedId) {
      nodeData.selected = true;
      this.selectedNode = nodeData;
    }
    return nodeData;
  }

  formateCommonComps() {
    /*
    let commonCompsList: string[] = [];
    this.componentConfigurationModel.siderbarConfig.forEach(item => {
      item.children.forEach(child => {
        if (child?.shapeKey) {
          commonCompsList.push(child.shapeKey);
        }
      });
    });
      this.commonTreeData[0].children.forEach(item => {
      if (commonCompsList.includes(item.shapeKey)) {
        item.disabled = true;
      }
    });
    */
  }

  handleTabClick(tab) {
    this.curTab = tab;
  }

  // 树上高亮
  async selectOnTree(id: string) {
    const nodes = await modelService.getNodePath(this.currentProjectId, id); // 根节点到此节点的路径
    const newNodes = [...nodes];
    newNodes.pop(); // 最后一个节点不用展开

    for (let node of newNodes) {
      const treeNode = this.nodeMap.get(node.id);
      if (!treeNode) return;
      if (treeNode.loaded) {
        treeNode.expand = true;
      } else {
        await this.loadNodes(treeNode);
        treeNode.expand = true;
      }
    }
    const targetNode = this.nodeMap.get(id);
    if (targetNode) {
      this.handleNodeClick(targetNode);
      nextTick(() => {
        const dom = document.getElementById(id);
        if (dom) {
          dom.scrollIntoView({ behavior: "smooth", block: "center", inline: "nearest" });
        }
      });
    } else {
      console.error("not found targetNode");
    }
  }

  handleNodeClick(node: MTreeNode) {
    if (this.selectedNode !== node) {
      if (this.selectedNode) {
        this.selectedNode.selected = false;
      }
      node.selected = true;
      this.selectedNode = node;

      this.selectedId = node.id as string;
    }
  }

  handleCommonNodeClick(node: CommonNode) {
    if (this.selectedCommonNode !== node) {
      if (this.selectedCommonNode) {
        this.selectedCommonNode.selected = false;
      }
      node.selected = true;
      this.selectedCommonNode = node;
    }
  }

  async loadNodes(parentNode: MTreeNode<any>) {
    let childNodeDatas;

    childNodeDatas = await modelService.getSelectableChildren(parentNode.data.projectId, parentNode.data.id, this.checkPropertyValueDto!);
    const nodes = childNodeDatas.map(data => this.createNode(data));
    this.sortChildren(nodes);
    nodes.forEach(node => {
      this.nodeMap.set(node.id as string, node);
      // 组件区配置处理： 非元类或构造型不可选择
      if (this.entryComp === "compsconfiguration" || this.entryComp === "containElement") {
        if (node.data.metaclass === MetaclassType.Stereotype || Object.keys(MetaclassType).includes(node.data.id)) {
          node.data.selectable = true;
        } else {
          node.data.selectable = false;
        }
      }
    });
    const relationNodes = nodes.filter(item => item.data?.type === ModelType.Relation);
    if (relationNodes.length > 0 && parentNode.data?.type !== ModelType.RelationGroup) {
      const relationGroup: MTreeNode = {
        data: {
          type: ModelType.RelationGroup,
          from: ModelFrom.USER_CREATE,
          name: "关系"
        },
        id: parentNode.id + "-relations",
        expand: false,
        selected: false,
        children: relationNodes,
        icon: "/statics/images/sysml/Relation.svg",
        name: "关系",
        disabled: true,
        loaded: true,
        isLeaf: false
      };
      parentNode.children = [relationGroup, ...nodes.filter(item => item.data?.type !== ModelType.Relation)];
    } else {
      parentNode.children = nodes;
    }
    parentNode.loaded = true;
    parentNode.loading = false;

    return nodes;
  }

  sortChildren(children: any) {
    SortNodeUtil.sortNodeChildren(children);
  }

  getChildren(node: MTreeNode) {
    return node.children?.filter(item => item.show !== false) || [];
  }

  // 删除某个已选组件或全部清除，需要将这些组件的disabled变为false，保证在模型树上可选
  updateNodeDiabled(nodeIds: string[], type: "tree" | "common" = "tree") {
    nodeIds.forEach(item => {
      if (type === "tree") {
        const treeNode = this.nodeMap.get(item as string);
        if (treeNode) {
          treeNode.disabled = false;
        }
      } else if (type === "common") {
        const treeNode = this.nodeCommonMap.get(item as string);
        if (treeNode) {
          treeNode.disabled = false;
        }
      }
    });
  }
}
